package com.sjp.myspring.beans.factory.support;

import com.sjp.myspring.annotation.JPAutowired;
import com.sjp.myspring.annotation.JPController;
import com.sjp.myspring.annotation.JPService;
import com.sjp.myspring.beans.JPBeanWrapper;
import com.sjp.myspring.beans.factory.JPBeanFactory;
import com.sjp.myspring.beans.factory.config.JPBeanDefinition;
import com.sjp.myspring.utils.StringUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class JPDefaultListableBeanFactory implements JPBeanFactory {
    //存储注册信息的BeanDefinition
    private final Map<String, JPBeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    private final Map<String, JPBeanWrapper> factoryBeanInstanceCache = new ConcurrentHashMap<>();

    @Override
    public Object getBean(String beanName) throws Exception {
        //分成两步，防止循环依赖
        JPBeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        //1.初始化
        JPBeanWrapper beanWrapper = instantiateBean(beanName, beanDefinition);
        //Object instance = beanWrapper.getWrappedInstance();
        //JPBeanPostProcessor beanPostProcessor = new JPBeanPostProcessor();
        //
        //beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
        //
        //beanPostProcessor.postProcessAfterInitialization(instance, beanName);

        //2.注入
        populateBean(beanName, beanDefinition, beanWrapper);

        return this.factoryBeanInstanceCache.get(beanName).getWrappedInstance();
    }

    @Override
    public Object getBean(Class<?> clazz) throws Exception {
        return getBean(clazz.getName());
    }

    @Override
    public String[] getBeanDefinitionNames() {
        return StringUtils.toStringArray(beanDefinitionMap.keySet());
    }

    @Override
    public int getBeanDefinitionCount() {
        return beanDefinitionMap.size();
    }

    private JPBeanWrapper instantiateBean(String beanName, JPBeanDefinition beanDefinition) {
        // 1、拿到要实例化的类名
        String className = beanDefinition.getBeanClassName();
        Object instance = null;

        try {
            if (singletonObjects.containsKey(className)) {
                instance = singletonObjects.get(className);
            } else {
                // 2、反射实例化，得到一个对象
                Class<?> clazz = Class.forName(className);
                instance = clazz.newInstance();
                singletonObjects.put(className, instance);
                singletonObjects.put(beanDefinition.getFactoryBeanName(), instance);
            }


        } catch (Exception e) {
            e.printStackTrace();
        }

        // 3、把对象封装到BeanWrapper中
        JPBeanWrapper beanWrapper = new JPBeanWrapper(instance);
        //factoryBeanInstanceCache

        // 4、把BeanWrapper放到IOC容器中
        factoryBeanInstanceCache.put(beanName, beanWrapper);
        return beanWrapper;
    }

    private void populateBean(String beanName, JPBeanDefinition beanDefinition, JPBeanWrapper beanWrapper) {
        Object instance = beanWrapper.getWrappedInstance();

        //判断只有加了注解的类才进行依赖注入
        Class<?> wrappedClass = beanWrapper.getWrappedClass();
        if (wrappedClass.isAnnotationPresent(JPController.class)
                || wrappedClass.isAnnotationPresent(JPService.class)) {

            for (Field field : wrappedClass.getDeclaredFields()) {
                if (!field.isAnnotationPresent(JPAutowired.class)) {
                    continue;
                }
                String autowiredBeanName = field.getType().getName();

                field.setAccessible(true);
                JPBeanWrapper beanWrapper1 = factoryBeanInstanceCache.get(autowiredBeanName);
                if (beanWrapper1 != null) {
                    try {
                        field.set(instance, beanWrapper1.getWrappedInstance());
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }


            }

        }


    }

    public void doRegisterBeanDefinition(List<JPBeanDefinition> beanDefinitions) {
        for (JPBeanDefinition beanDefinition : beanDefinitions) {
            beanDefinitionMap.put(beanDefinition.getFactoryBeanName(), beanDefinition);
            beanDefinitionMap.put(beanDefinition.getBeanClassName(), beanDefinition);
        }
    }

    /**
     * 不是延时加载的类，提前初始化
     */
    public void doAutowire() {
        for (Map.Entry<String, JPBeanDefinition> entry : beanDefinitionMap.entrySet()) {
            if (!entry.getValue().isLazyInit()) {
                String beanName = entry.getKey();
                try {
                    getBean(beanName);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
